#import <UIKit/UIKit.h>
#import "OTATool.h"
#import "OTA.h"

NSString *const OTA_FRI_service = @"02F00000-0000-0000-0000-00000000FE00";
NSString *const OTA_FRI_char_write = @"02F00000-0000-0000-0000-00000000FF01";
NSString *const OTA_FRI_char_read = @"02F00000-0000-0000-0000-00000000FF02";

@interface OTATool ()

@property (nonatomic, strong) NSData *firstAddress;
@property (nonatomic, assign) int crc;
@property (nonatomic, strong) NSData *bin;
@property (nonatomic, assign, readonly) NSUInteger page_4096;
@property (nonatomic, assign, readonly) NSUInteger page_235;

@end

@implementation OTATool

static OTATool *sharedInstance = nil;

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (NSUInteger)page_4096 {
    return (self.bin.length + 4095) / 4096; // 简化计算
}

- (NSUInteger)page_235 {
    return (self.bin.length + 234) / 235; // 简化计算
}

- (void)reset {
    self.firstAddress = [NSData data];
    self.crc = 0;
    self.bin = [NSData data];
}

///1， 预OTA，读取首地址
- (void)prepareWith:(nonnull NSData *)binData {
    [self reset];
    self.bin = binData;
    self.crc = [OTA crc32ForBinFile:self.bin];
    
    if ([self.delegate respondsToSelector:@selector(readStorageAddress:serviceUUID:charUUID:)]) {
        Byte bytes[] = {0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
        NSData *data = [NSData dataWithBytes:bytes length:7];
        [self.delegate readStorageAddress:data serviceUUID:OTA_FRI_service charUUID:OTA_FRI_char_write];
    }
}

/// 2，擦除地址
/// - Parameter address: 要擦出的地址
- (void)clear:(nonnull NSData *)address {
    NSInteger current_num = [self dataToNSInteger:address];
    NSInteger start_num = [self dataToNSInteger:self.firstAddress];
    NSInteger page = (current_num - start_num) / 4096;
    
    if (page < self.page_4096) {
        if ([self.delegate respondsToSelector:@selector(clearAddress:progress:serviceUUID:charUUID:)]) {
            NSData *data_current = [self reverse:address];
            data_current = [self pad:data_current toLength:4];
            
            Byte bytes[] = {0x03, 0x04, 0x00};
            NSData *cmd = [NSData dataWithBytes:bytes length:sizeof(bytes)];
            
            NSMutableData *data = [NSMutableData data];
            [data appendData:cmd];
            [data appendData:data_current];
            
            CGFloat progress = (CGFloat)(page + 1) / self.page_4096;
            [self.delegate clearAddress:data progress:progress serviceUUID:OTA_FRI_service charUUID:OTA_FRI_char_write];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.03 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSInteger next = current_num + 4096;
                [self clear:[self reverse:[self NSIntegerToData:next]]];
            });
        }
    }
}

/// 3，写入数据
/// - Parameter address: 写入地址
- (void)send:(NSData *)address {
    if (address.length == 0) return;
    
    NSInteger current_num = [self dataToNSInteger:address];
    NSInteger start_num = [self dataToNSInteger:self.firstAddress];
    NSInteger page = (current_num - start_num) / 235;
    
    if (page < self.page_235) {
        NSInteger s = page * 235;
        NSInteger e = MIN(page * 235 + 235, self.bin.length);
        NSData *temp = [self.bin subdataWithRange:NSMakeRange(s, e - s)];
        
        if ([self.delegate respondsToSelector:@selector(writeData:progress:serviceUUID:charUUID:)]) {
            Byte bytes[] = {0x05, 0x41, 0x02};
            NSData *cmd = [NSData dataWithBytes:bytes length:sizeof(bytes)];
            
            NSData *data_address = [self reverse:address];
            data_address = [self pad:data_address toLength:4];
            
            Byte end_bytes[] = {0xEB, 0x00};
            NSData *end = [NSData dataWithBytes:end_bytes length:sizeof(end_bytes)];
            
            NSMutableData *data = [NSMutableData data];
            [data appendData:cmd];
            [data appendData:data_address];
            [data appendData:end];
            [data appendData:temp];
            
            CGFloat progress = (CGFloat)(page + 1) / self.page_235;
            [self.delegate writeData:data progress:progress serviceUUID:OTA_FRI_service charUUID:OTA_FRI_char_write];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSInteger next = current_num + 235;
                [self send:[self reverse:[self NSIntegerToData:next]]];
            });
        }
    }
}
#pragma mark -  蓝牙数据的回调
- (void)handleData:(CBPeripheral *)peripheral didUpdateValueFor:(CBCharacteristic *)characteristic error:(NSError *)error {
    if ([characteristic.UUID.UUIDString.uppercaseString isEqualToString:OTA_FRI_char_read]) {
        const uint8_t *bytes = characteristic.value.bytes;
        NSInteger start = 4;
        NSInteger length = 4;
        switch (bytes[1]) {
            case 0x01:///读取起始位置的回调
                if (bytes[0] == 0x00) {
                    NSData *address_data = [NSData dataWithBytes:bytes + start length:length];
                    self.firstAddress = [self reverse:address_data];
                    [self clear:self.firstAddress];
                }
            case 0x03:///擦除地址回调
                if (bytes[0] == 0x00) {
                    NSData *address_data = [NSData dataWithBytes:bytes + start length:length];
                    address_data = [self reverse:address_data];
                    NSInteger curent_address = [self dataToNSInteger:address_data];
                    NSInteger start_address = [self dataToNSInteger:self.firstAddress];
                    NSInteger current_page = (curent_address - start_address) / 4096 + 1;
                    
                    ///⚠️当擦除了最后一个地址，则开始写入数据
                    if (self.page_4096 == current_page) {
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            [self send:self.firstAddress];
                        });
                    }
                }
            case 0x05:///写入数据回调
                if (bytes[0] == 0x00) {
                    NSData *address_data = [NSData dataWithBytes:bytes + 4 length:4];
                    address_data = [self reverse:address_data];
                    NSInteger curent_address = [self dataToNSInteger:address_data];
                    NSInteger start_address = [self dataToNSInteger:self.firstAddress];
                    NSInteger current_page = (curent_address - start_address) / 235 + 1;
                    
                    ///⚠️当写入最后一个分包数据，则开始重启设备
                    if (self.page_235 == current_page) {
                        if ([self.delegate respondsToSelector:@selector(shouldResetWithSuccessDone:serviceUUID:charUUID:)]) {
                            Byte bytes[] = {0x09, 0x08, 0x00};
                            NSData *cmd = [NSData dataWithBytes:bytes length:sizeof(bytes)];
                            NSData *data_length = [self NSIntegerToData:self.bin.length];
                            data_length = [self pad:data_length toLength:4];
                            NSData *data_crc = [self NSIntegerToData:self.crc];
                            data_crc = [self pad:data_crc toLength:4];
                            
                            NSMutableData *data = [NSMutableData data];
                            [data appendData:cmd];
                            [data appendData:data_length];
                            [data appendData:data_crc];
                            [self.delegate shouldResetWithSuccessDone:data serviceUUID:OTA_FRI_service charUUID:OTA_FRI_char_write];
                        }
                    }
                }
            default:
                break;
        }
    }
}

#pragma mark - 辅助方法
///倒叙
- (NSData *)reverse:(NSData *)data {
    const uint8_t *bytes = data.bytes;
    NSUInteger length = data.length;
    NSMutableData *reversedData = [NSMutableData dataWithLength:length];
    uint8_t *reversedBytes = reversedData.mutableBytes;
    for (NSUInteger i = 0; i < length; i++) {
        reversedBytes[i] = bytes[length - 1 - i];
    }
    return [reversedData copy];
}

/// NSData转换成NSUInteger
- (NSUInteger)dataToNSInteger:(NSData *)data {
    const uint8_t *bytes = [data bytes];
    NSInteger value = 0;
    for (NSInteger i = 0; i < data.length; i++) {
        value = (value << 8) | bytes[i];
    }
    return value;
}

/// NSUInteger转换成NSData
- (NSData *)NSIntegerToData:(NSUInteger)value {
    uint32_t fixedValue = (uint32_t)value; // 强制转换为 4 字节
    return [NSData dataWithBytes:&value length:sizeof(fixedValue)];
}


/// NSData指定长度，不足以“0”补齐
- (NSData *)pad:(NSData *)data toLength:(NSUInteger)length {
    NSMutableData *paddedData = [data mutableCopy];
    while (paddedData.length < length) {
        [paddedData appendBytes:"\0" length:1];
    }
    return [paddedData copy];
}

@end
